package api

import (
	"context"
	"fmt"
	"time"

	"dev.ixmxm.top/rms/boot"
	"dev.ixmxm.top/rms/codes"
	"dev.ixmxm.top/rms/managers/robotmanager"
	"dev.ixmxm.top/rms/model"
	"dev.ixmxm.top/rms/proto"
	"dev.ixmxm.top/rms/utils/log"
	"dev.ixmxm.top/rms/utils/tools"
	"github.com/gin-gonic/gin"
)

// @Summary 任务添加(所有任务，包含充电与断电任务)
// @Description
// @Accept application/json
// @Produce application/json
// @Param body body model.Task true "任务"
// @Success 0 {object} ResponseExample "返回数据格式"
// @Tags 任务
// @Router /task/add_task [post]
func (hg *HttpGateway) AddTask(ctx context.Context, params interface{}) (interface{}, codes.Code) {
	p := params.(*addTaskParams)
	if p == nil {
		return nil, codes.ErrInvalidParams.WithDetails("解析参数有误")
	}
	var robot *model.Robot = nil
	if p.AgvId != "" {
		robot = robotmanager.GetFromCache(p.AgvId)
		if robot == nil {
			return nil, codes.ErrRobotNotExists
		}
		/*isAny := false
		for _, mapName := range robot.Account.MapList {
			if mapName == p.MapName {
				isAny = true
			}
		}
		if !isAny {
			return nil, codes.ErrInvalidParams.WithDetails("该小车不可在此地图上执行")
		}*/
	}
	if p.Type == model.TaskTypeCharge || p.Type == model.TaskTypeDisCharge {
		if robot == nil {
			return nil, codes.ErrRobotNotExists
		}
		return hg.manualCharge(ctx, p)
	}
	if p.Type == model.TaskTypeStandBy && p.AgvId != "" {
		standby, err := hg.dispatcher.TRM().GetStandbySite(ctx, p.MapName, p.TargetSiteID)
		if err != nil {
			return nil, err
		}
		for _, robotId := range standby.BanAgvList {
			if robotId == p.AgvId {
				return nil, codes.ErrInvalidParams.WithDetails("该待命点已禁用该小车")
			}
		}
	}
	return hg.addTask(ctx, p)
}

//任务添加(不可下发充电与断电任务)
func (hg *HttpGateway) addTask(ctx context.Context, p *addTaskParams) (interface{}, codes.Code) {
	if p.ExternalTaskCode != "" {
		isExists, err := hg.dispatcher.TM().TaskExistsFromDBByExternalTaskCode(ctx, p.ExternalTaskCode)
		if err != nil {
			return nil, err
		}
		if isExists {
			return nil, codes.ErrTaskExists
		}
	}
	task := p.Task
	task.Status = model.TaskStatusRegister
	task.CreatedTime = time.Now()
	if task.Type == model.TaskTypeCharge {
		task.Grade = 99
	} else if task.Type == model.TaskTypeStandBy {
		task.Grade = 1
	}
	task.TargetID = task.TargetSiteID
	t, err := hg.dispatcher.TM().AddToDB(ctx, &task)
	if err != nil {
		log.ErrorfWithContext(ctx, "add task error:%s", err.Error())
		return nil, err
	}
	return gin.H{"task_id": t.Id, "created_time": t.CreatedTime}, nil
}

//手动开始/结束充电
func (hg *HttpGateway) manualCharge(ctx context.Context, p *addTaskParams) (interface{}, codes.Code) {
	if !robotmanager.GetFromCache(p.AgvId).Account.AutoCharge {
		return nil, codes.ErrRobotDisableCharge
	}
	chargers := hg.dispatcher.CM().GetAllChargersFromCache(ctx)
	isAnyCharge := false
	var chargerId uint8
	for _, chargr := range chargers {
		if chargr.GetInfo().SiteId == p.TargetSiteID && chargr.GetInfo().MapName == p.MapName {
			isAnyCharge = true
			chargerId = chargr.GetInfo().Id
			if p.Type == model.TaskTypeCharge {
				if chargr.GetInfo().AgvID != "" {
					return nil, codes.ErrChargeLocked
				}
				if chargr.GetStatusWord().Code != 0 {
					return nil, codes.ErrChargerStatusNotMatch.WithDetails("充电桩存在故障")
				}
				for _, banAgv := range chargr.GetInfo().BanAgvList {
					if banAgv == p.AgvId {
						return nil, codes.ErrInvalidParams.WithDetails("该充电桩已禁用此小车充电")
					}
				}
			}
			if p.Type == model.TaskTypeDisCharge && chargr.GetInfo().AgvID == "" {
				return nil, codes.ErrInvalidParams.WithDetails("充电桩已释放")
			}
			if p.Type == model.TaskTypeDisCharge && chargr.GetInfo().AgvID != "" {
				//判断规则是否超标
				if chargr.GetInfo().Rule.IsUse {
					//那就先判断规则结束时间
					currentBeijinTime := tools.GetCurrentTiemByshanghai()
					ruleEndTime := tools.GetCurrentTiemByshanghai1(chargr.GetInfo().Rule.EndTime)

					if currentBeijinTime.Sub(ruleEndTime) <= 0 {
						ruleStr := fmt.Sprintf("%d", chargr.GetInfo().Rule.RuleId)
						log.Errorf("还存在定时充电规则内(规则：%s )不可手动打断", ruleStr)
						return nil, codes.ErrInvalidParams.WithDetails("还存在定时充电规则内(规则：" + ruleStr + ")不可手动打断")
					}
				}
			}
		}
	}
	if !isAnyCharge {
		return nil, codes.ErrChargerNotFound
	}
	switch p.Type {
	case model.TaskTypeCharge: //充电
		hg.dispatcher.AddManualCharge(p.AgvId, chargerId)
	case model.TaskTypeDisCharge: //断电
		hg.dispatcher.AddDisCharge(p.AgvId, chargerId)
	}
	return nil, nil
}

// @Summary 删除一条任务
// @Description
// @Accept application/json
// @Produce application/json
// @Param task_id query uint64 true "任务ID"
// @Success 0 {object} ResponseExample "返回数据格式"
// @Tags 任务
// @Router /task/delete_task [delete]
func (hg *HttpGateway) DeleteTask(ctx context.Context, params interface{}) (interface{}, codes.Code) {
	p := params.(*getTaskParams)
	err := hg.dispatcher.TM().DeleteTaskToDB(ctx, p.TaskID)
	if err != nil {
		log.ErrorWithContext(ctx, "get task error:", err.UnWrapError())
		return nil, err
	}
	return nil, nil
}

// @Summary 清空任务
// @Description
// @Accept application/json
// @Produce application/json
// @Success 0 {object} ResponseExample "返回数据格式"
// @Tags 任务
// @Router /task/clear_task [delete]
func (hg *HttpGateway) ClearTask(ctx context.Context, params interface{}) (interface{}, codes.Code) {
	err := hg.dispatcher.TM().ClearTaskToDB(ctx)
	if err != nil {
		log.ErrorWithContext(ctx, "get task error:", err.UnWrapError())
		return nil, err
	}
	return nil, nil
}

// @Summary 查询一条任务
// @Description
// @Accept application/json
// @Produce application/json
// @Param task_id query uint64 true "任务ID"
// @Success 0 {object} ResponseExampleStruct "返回数据格式"
// @Success 1 {object} model.Task "data数据：任务"
// @Tags 任务
// @Router /task/get_task [get]
func (hg *HttpGateway) GetTask(ctx context.Context, params interface{}) (interface{}, codes.Code) {
	p := params.(*getTaskParams)
	task, err := hg.dispatcher.TM().GetTaskFromDB(ctx, p.TaskID)
	if err != nil {
		log.ErrorWithContext(ctx, "get task error:", err.UnWrapError())
		return nil, err
	}
	return task, nil
}

// @Summary 查询任务集合,开始执行任务的时间区间
// @Description
// @Accept application/json
// @Produce application/json
// @Param type query int true "任务类型"
// @Param time_from query int64 true "开始时间戳"
// @Param time_to query int64 true "结束时间戳"
// @Success 0 {object} ResponseExampleStruct "返回数据格式"
// @Success 1 {object} []model.Task "list数据：任务集合"
// @Tags 任务
// @Router /task/get_task_by_time [get]
func (hg *HttpGateway) GetByTimeTasks(ctx context.Context, params interface{}) (interface{}, codes.Code) {
	p := params.(*getTaskTimeParams)
	var status []model.TaskStatus

	//获得时间段
	var from, end time.Time
	if p.TimeFrom != 0 {
		from = time.Unix(p.TimeFrom, 0)
	}
	if p.TimeTo != 0 {
		end = time.Unix(p.TimeTo, 0)
	}
	log.Infof("get rms logs:from:%s,to:%s,query type:%d", from.Local(), end.Local(), p.Type)

	switch p.Type {
	case 0:
		status = []model.TaskStatus{}
	case 1:
		status = model.TaskRunningStatus()
	case 2:
		status = model.TaskWaitingStatus()
	case 3:
		status = []model.TaskStatus{model.TaskStatusCanceled, model.TaskStatusError}
	case 4:
		status = []model.TaskStatus{model.TaskStatusFinish}
	case 5:
		status = model.TaskAssignStatus()
	default:
		return nil, codes.ErrInvalidParams
	}

	tasks, err := hg.dispatcher.TM().GetStatusByTimeTaskForPageFromDB(ctx, from, end, status)
	if err != nil {
		log.ErrorWithContext(ctx, "get tasks error:", err.UnWrapError())
		return nil, err
	}
	return tasks, nil
}

// @Summary 查询任务集合
// @Description
// @Accept application/json
// @Produce application/json
// @Param type query int true "任务类型"
// @Param page_size query int64 true "每页记录数量"
// @Param page_index query int64 true "当前页码"
// @Success 0 {object} ResponseExampleStruct "返回数据格式"
// @Success 1 {object} page.PageResultExample "data数据：分页信息"
// @Success 2 {object} []model.Task "list数据：任务集合"
// @Tags 任务
// @Router /task/get_tasks [get]
func (hg *HttpGateway) GetTasks(ctx context.Context, params interface{}) (interface{}, codes.Code) {
	p := params.(*getTasksParams)
	var status []model.TaskStatus
	switch p.Type {
	case 0:
		status = []model.TaskStatus{}
	case 1:
		status = model.TaskRunningStatus()
	case 2:
		status = model.TaskWaitingStatus()
	case 3:
		status = []model.TaskStatus{model.TaskStatusCanceled, model.TaskStatusError}
	case 4:
		status = []model.TaskStatus{model.TaskStatusFinish}
	case 5:
		status = model.TaskAssignStatus()
	default:
		return nil, codes.ErrInvalidParams
	}

	tasks, pageResult, err := hg.dispatcher.TM().GetStatusTaskForPageFromDB(ctx, status, p.Params)
	if err != nil {
		log.ErrorWithContext(ctx, "get tasks error:", err.UnWrapError())
		return nil, err
	}
	return pageResult.Json(tasks), nil
}

// @Summary 查询任务集合，根据RMS任务编号
// @Description
// @Accept application/json
// @Produce application/json
// @Param type query int true "任务类型"
// @Param task_id query uint64 true "任务ID"
// @Param page_size query int64 true "每页记录数量"
// @Param page_index query int64 true "当前页码"
// @Success 0 {object} ResponseExampleStruct "返回数据格式"
// @Success 1 {object} page.PageResultExample "data数据：分页信息"
// @Success 2 {object} []model.Task "list数据：任务集合"
// @Tags 任务
// @Router /task/get_tasks_by_taskId [get]
func (hg *HttpGateway) GetTasksByRmsTaskId(ctx context.Context, params interface{}) (interface{}, codes.Code) {
	p := params.(*getTasksByRmsTaskId)
	var status []model.TaskStatus
	switch p.Type {
	case 0:
		status = []model.TaskStatus{}
	case 1:
		status = model.TaskRunningStatus()
	case 2:
		status = model.TaskWaitingStatus()
	case 3:
		status = []model.TaskStatus{model.TaskStatusCanceled, model.TaskStatusError}
	case 4:
		status = []model.TaskStatus{model.TaskStatusFinish}
	case 5:
		status = model.TaskAssignStatus()
	default:
		return nil, codes.ErrInvalidParams
	}
	//当前RMS任务号的所有任务
	tasks, pageResult, err := hg.dispatcher.TM().GetStatusTaskForPagebyTaskIdFromDB(ctx, status, p.Params, p.TaskId)
	if err != nil {
		log.ErrorWithContext(ctx, "get tasks error:", err.UnWrapError())
		return nil, err
	}
	return pageResult.Json(tasks), nil
}

// @Summary 查询任务集合,根据主任务编号的模拟
// @Description
// @Accept application/json
// @Produce application/json
// @Param type query int true "任务类型"
// @Param main_task_code query string true "模糊住任务编号"
// @Param page_size query int64 true "每页记录数量"
// @Param page_index query int64 true "当前页码"
// @Success 0 {object} ResponseExampleStruct "返回数据格式"
// @Success 1 {object} page.PageResultExample "data数据：分页信息"
// @Success 2 {object} []model.Task "list数据：任务集合"
// @Tags 任务
// @Router /task/get_tasks_like_maintaskcode [get]
func (hg *HttpGateway) GetTasksLikeMainTaskCode(ctx context.Context, params interface{}) (interface{}, codes.Code) {
	p := params.(*getTasksByMainTaskCode)
	var status []model.TaskStatus
	switch p.Type {
	case 0:
		status = []model.TaskStatus{}
	case 1:
		status = model.TaskRunningStatus()
	case 2:
		status = model.TaskWaitingStatus()
	case 3:
		status = []model.TaskStatus{model.TaskStatusCanceled, model.TaskStatusError}
	case 4:
		status = []model.TaskStatus{model.TaskStatusFinish}
	case 5:
		status = model.TaskAssignStatus()
	default:
		return nil, codes.ErrInvalidParams
	}

	tasks, pageResult, err := hg.dispatcher.TM().GetStatusTaskForPagebyMainTaskCodeFromDB(ctx, status, p.Params, p.MainTaskCode)
	if err != nil {
		log.ErrorWithContext(ctx, "get tasks error:", err.UnWrapError())
		return nil, err
	}
	return pageResult.Json(tasks), nil
}

// @Summary 查询任务集合,根据主任务编号的模拟
// @Description
// @Accept application/json
// @Produce application/json
// @Param type query int true "任务类型"
// @Param task_id query uint64 false "任务ID"
// @Param main_task_code query string false "模糊住任务编号"
// @Param page_size query int64 true "每页记录数量"
// @Param page_index query int64 true "当前页码"
// @Success 0 {object} ResponseExampleStruct "返回数据格式"
// @Success 1 {object} page.PageResultExample "data数据：分页信息"
// @Success 2 {object} []model.Task "list数据：任务集合"
// @Tags 任务
// @Router /task/get_tasks_by_keys [get]
func (hg *HttpGateway) GetTasksByKeys(ctx context.Context, params interface{}) (interface{}, codes.Code) {
	p := params.(*getTasksByKeys)
	var status []model.TaskStatus
	switch p.Type {
	case 0:
		status = []model.TaskStatus{}
	case 1:
		status = model.TaskRunningStatus()
	case 2:
		status = model.TaskWaitingStatus()
	case 3:
		status = []model.TaskStatus{model.TaskStatusCanceled, model.TaskStatusError}
	case 4:
		status = []model.TaskStatus{model.TaskStatusFinish}
	case 5:
		status = model.TaskAssignStatus()
	default:
		return nil, codes.ErrInvalidParams
	}
	tasks, pageResult, err := hg.dispatcher.TM().GetStatusTaskForPagebyKeysFromDB(ctx, status, p.Params, p.MainTaskCode, p.TaskId)
	if err != nil {
		log.ErrorWithContext(ctx, "get tasks error:", err.UnWrapError())
		return nil, err
	}
	return pageResult.Json(tasks), nil
}

// @Summary 查询所有子任务
// @Description
// @Accept application/json
// @Produce application/json
// @Success 0 {object} ResponseExampleList "返回数据格式"
// @Success 1 {object} []model.Subtask "data数据：子任务集合"
// @Tags 任务
// @Router /task/get_subtasks [get]
func (hg *HttpGateway) GetSubtasks(ctx context.Context, params interface{}) (interface{}, codes.Code) {
	subtasks, err := hg.dispatcher.TM().GetAllSubtaskFromDB(ctx)
	if err != nil {
		log.ErrorWithContext(ctx, "get tasks error:", err.UnWrapError())
		return nil, err
	}
	return subtasks, nil
}

// @Summary 查询任务编号下所有子任务
// @Description
// @Accept application/json
// @Produce application/json
// @Param task_id query uint64 true "任务ID"
// @Success 0 {object} ResponseExampleList "返回数据格式"
// @Success 1 {object} []model.Subtask "data数据：子任务集合"
// @Tags 任务
// @Router /task/get_subtasks_by_taskid [get]
func (hg *HttpGateway) GetSubTasksByTaskId(ctx context.Context, params interface{}) (interface{}, codes.Code) {
	p := params.(*getTaskParams)
	subtasks, err := hg.dispatcher.TM().GetAllSubtasksByTaskIdFromDB(ctx, p.TaskID)
	if err != nil {
		log.ErrorWithContext(ctx, "get tasks error:", err.UnWrapError())
		return nil, err
	}
	return subtasks, nil
}

// @Summary 查询所有任务绑定信息
// @Description
// @Accept application/json
// @Produce application/json
// @Success 0 {object} ResponseExampleList "返回数据格式"
// @Success 1 {object} []model.MainTask "data数据：任务绑定信息集合"
// @Tags 任务
// @Router /task/get_task_bindings [get]
func (hg *HttpGateway) GetTaskBindings(ctx context.Context, params interface{}) (interface{}, codes.Code) {
	tasks, errGetTasks := hg.dispatcher.TM().GetAllMainTasksFromDB(ctx)
	if errGetTasks != nil {
		log.ErrorfWithContext(ctx, "get all main tasks error:%s", errGetTasks.UnWrapError())
		return nil, errGetTasks
	}
	return tasks, nil
}

// @Summary 根据主任务编号获取主任务下所有任务信息
// @Description
// @Accept application/json
// @Produce application/json
// @Param main_task_code query string true "主任务编号"
// @Success 0 {object} ResponseExampleList "返回数据格式"
// @Success 1 {object} []model.Task "data数据：任务集合"
// @Tags 任务
// @Router /task/get_tasks_by_maintaskcode [get]
func (hg *HttpGateway) GetTasksByMainTaskCode(ctx context.Context, params interface{}) (interface{}, codes.Code) {
	p := params.(*getTaskStreamParams)
	tasks, errGetTasks := hg.dispatcher.TM().GetTasksByMainTaskCodeFromDB(ctx, p.MainTaskCode)
	if errGetTasks != nil {
		log.ErrorfWithContext(ctx, "get tasks stream error:%s", errGetTasks.UnWrapError())
		return nil, errGetTasks
	}
	return tasks, nil
}

// @Summary 解除机器人主任务绑定
// @Description
// @Accept application/json
// @Produce application/json
// @Param body body unlockMainTaskParams true " "
// @Success 0 {object} ResponseExample "返回数据格式"
// @Tags 任务
// @Router /task/unlock_maintask [post]
func (hg *HttpGateway) UnlockMainTask(ctx context.Context, params interface{}) (interface{}, codes.Code) {
	p := params.(*unlockMainTaskParams)
	//该主任务下的任务全部完成或取消时才可进行解除
	tasks, err := hg.dispatcher.TM().GetAllTasksByMainTaskCodeFromDB(ctx, p.MainTaskCode)
	if err != nil {
		return nil, err
	}
	for _, task := range tasks {
		//判断任务为空闲避让，行走任务，并且任务状态为已等级或者已分配，强制完成
		if task.Type == model.TaskTypeAvoid && (task.Status == model.TaskStatusRegister || task.Status == model.TaskStatusAssign) {
			//强制取消所有的已登记和已分配的空闲避让任务
			err1 := hg.dispatcher.TM().UpdateTaskStatusToDB(context.Background(), task.Id, model.TaskStatusCanceled)
			if err1 != nil {
				return nil, codes.ErrFreeAvoidCanceld
			}
			//删除对应子任务
			err1 = hg.dispatcher.TM().DeleteSubtasksToDB(ctx, task.Id)
			if err1 != nil {
				return nil, codes.ErrFreeAvoidCanceld
			}
		}
		if task.Type != model.TaskTypeAvoid && !(task.Status == model.TaskStatusFinish || task.Status == model.TaskStatusCanceled) {
			return nil, codes.ErrTaskStatusNotMatch
		}
	}
	log.Warnf("robot:%s DeleteMainTaskToDB %s", tasks[0].AgvId, p.MainTaskCode)
	return nil, hg.dispatcher.TM().DeleteMainTaskToDB(ctx, p.MainTaskCode)
}

// @Summary 手动操作任务接口
// @Description
// @Accept application/json
// @Produce application/json
// @Param body body operateTaskParams true " "
// @Success 0 {object} ResponseExample "返回数据格式"
// @Tags 任务
// @Router /task/operate_task [post]
func (hg *HttpGateway) OperateTask(ctx context.Context, params interface{}) (interface{}, codes.Code) {
	p := params.(*operateTaskParams)
	log.Info("API OperateTask Receive data:%v", p)
	//获取任务
	task, errGet := hg.dispatcher.TM().GetTaskFromDB(ctx, p.TaskID)
	if errGet != nil {
		log.ErrorfWithContext(ctx, "get task:%d error:%s", p.TaskID, errGet.Error())
		return nil, errGet
	}
	if task == nil {
		log.ErrorfWithContext(ctx, "get task:%d error:%s", p.TaskID, "任务不存在")
		return nil, codes.ErrTaskNotExists
	}
	if task.Type == model.TaskTypeCharge && task.Status == model.TaskStatusCharging &&
		(p.OperateCMD == model.TaskOperateExec || p.OperateCMD == model.TaskOperatePause || p.OperateCMD == model.TaskOperateRetry) {
		log.ErrorfWithContext(ctx, "手动任务操作 task:%d error:充电中的任务不可进行暂停、继续、重发操作", p.TaskID)
		return nil, codes.ErrTaskStatusNotMatch
	}

	var (
		newTaskState          model.TaskStatus //任务新状态
		isUpdateTaskStatus    bool             //是否更新任务状态
		isUpdateSubtaskStatus bool             //是否更新子任务状态

		isOperateRobot   bool                //是否进行小车操作
		robotOperateCode proto.TaskOperatePb //任务操作类别

		freeCharger      bool //是否释放充电桩
		freeStandbyPoint bool //是否释放待命点
	)
	isUpdateTaskStatus = false
	if isUpdateTaskStatus {
	}
	isUpdateSubtaskStatus = false
	isOperateRobot = false
	freeCharger = false
	freeStandbyPoint = false

	switch p.OperateCMD {
	case model.TaskOperateExec:
		//任务正在运行或已完成，返回成功
		if task.Status.IsExecuting() || task.Status.IsDone() {
			return nil, nil
		}
		//任务不在暂停中，返回错误
		if task.Status != model.TaskStatusPaused {
			return nil, codes.ErrTaskStatusNotMatch
		}
		isUpdateSubtaskStatus = true
		newTaskState = model.TaskStatusContinuing
		isOperateRobot = true
		robotOperateCode = proto.TaskOperatePb_TaskContinue

	case model.TaskOperatePause:
		//任务已暂停、暂停中， 或已完成，返成功
		if task.Status.IsPause() || task.Status.IsDone() {
			return nil, nil
		}
		//任务不在运行中，返回错误
		if task.Status != model.TaskStatusRunning && task.Status != model.TaskStatusInTheTransit && task.Status != model.TaskStasusAvoid {
			return nil, codes.ErrTaskStatusNotMatch
		}
		//暂停任务
		isUpdateSubtaskStatus = true
		newTaskState = model.TaskStatusPausing
		isOperateRobot = true
		robotOperateCode = proto.TaskOperatePb_TaskPause

	case model.TaskOperateCancel:
		//任务已取消或已完成，返回成功
		if task.Status.IsDone() {
			return nil, nil
		}
		if task.Status.IsRunning() || task.Status == model.TaskStasusResolved {
			//取消任务
			isUpdateSubtaskStatus = true
			newTaskState = model.TaskStatusCanceling
			isOperateRobot = true
			robotOperateCode = proto.TaskOperatePb_TaskCancel
		} else {
			//待解析任务
			isUpdateTaskStatus = true
			newTaskState = model.TaskStatusCanceled
		}
		freeCharger = true
		freeStandbyPoint = true

	case model.TaskOperateForceFinish:
		if task.Status.IsDone() {
			return nil, nil
		}
		if task.Status.IsRunning() || task.Status == model.TaskStasusResolved {
			//操作小车取消任务
			isOperateRobot = true
			robotOperateCode = proto.TaskOperatePb_TaskFinish
			//改任务状态
			isUpdateSubtaskStatus = true
			newTaskState = model.TaskStatusInFinish
		} else {
			//改任务状态
			isUpdateTaskStatus = true
			newTaskState = model.TaskStatusFinish
		}
		//释放充电与待命点
		freeCharger = true
		freeStandbyPoint = true
	}

	ctxTx := boot.Begin(ctx)

	if task.AgvId == "" {
		isOperateRobot = false
	}

	//机器人任务操作
	if isOperateRobot {
		robot := robotmanager.GetFromCache(task.AgvId)
		if robot.StatusIsExists() && robot.Status.TaskOnline && robot.Status.ControlType == 1 &&
			robot.Status.Status != model.RobotStatusInit && robot.Status.Status != model.RobotStatusError &&
			robot.Status.Status != model.RobotStatusIdle && robot.Status.Status != model.RobotStatusStandby {
			//获取子任务
			runSubtask, err := hg.dispatcher.TM().GetRunningSubtaskFromDB(ctxTx, task.AgvId)
			if err != nil {
				ctxTx.Rollback()
				return nil, err.WithDetails("根据小车状态获取运行中的子任务失败")
			}
			caller, _ := hg.dispatcher.GetCaller(task.AgvId)
			if caller == nil {
				ctxTx.Rollback()
				return nil, codes.ErrRobotOperate.WithDetails("没有找到小车连接")
			}
			//充电任务中的任务
			if runSubtask.Type == model.TaskTypeCharge && (runSubtask.Status == model.TaskStatusCharging || runSubtask.Status == model.TaskStatusError) {
				//AGV发送断电
				errOperate := caller.DischargeTask(ctxTx)
				if errOperate != nil {
					log.ErrorfWithContext(ctxTx, "AGV发送断电 error:%s", errOperate.UnWrapError())
					ctxTx.Rollback()
					return nil, errOperate
				}

				//如果不需要操作小车，需要直接把任务改为已操作
				switch newTaskState {
				case model.TaskStatusInFinish:
					isUpdateTaskStatus = true
					isUpdateSubtaskStatus = false
					newTaskState = model.TaskStatusFinish

				case model.TaskStatusCanceling:
					isUpdateTaskStatus = true
					isUpdateSubtaskStatus = false
					newTaskState = model.TaskStatusCanceled
				}

			} else {
				errOperate := caller.OperateTask(ctxTx, runSubtask.Id, hg.dispatcher.TM(), robotOperateCode)
				// if robotOperateCode == proto.TaskOperatePb_TaskFinish || robotOperateCode == proto.TaskOperatePb_TaskCancel {
				// 	robot.Status.IsBlock = false
				// }
				if errOperate != nil {
					log.ErrorfWithContext(ctxTx, "operate task error:%s", errOperate.UnWrapError())
					ctxTx.Rollback()
					return nil, errOperate
				}
			}
		} else {
			//如果不需要操作小车，需要直接把任务改为已操作
			switch newTaskState {
			case model.TaskStatusInFinish:
				isUpdateTaskStatus = true
				isUpdateSubtaskStatus = false
				newTaskState = model.TaskStatusFinish

			case model.TaskStatusCanceling:
				isUpdateTaskStatus = true
				isUpdateSubtaskStatus = false
				newTaskState = model.TaskStatusCanceled

			case model.TaskStatusPausing:
				newTaskState = model.TaskStatusPaused
			}
		}
	}

	//更新任务状态
	// if isUpdateTaskStatus {
	isFirstTask := false //是否为第一条任务
	// (task.Status == model.TaskStatusRegister || p.CompleteType == CompleteTypeAbnomal) &&
	if p.CompleteType == model.CompleteTypeAbnomal && task.MainTaskCode != "" && (p.OperateCMD == model.TaskOperateForceFinish) {
		t, err := hg.dispatcher.TM().GetFirstTaskByMainTaskCodeFromDB(ctxTx, task.MainTaskCode)
		if err != nil {
			ctxTx.Rollback()
			return nil, err
		}
		if t.Id == task.Id {
			isFirstTask = true

			tasks, err := hg.dispatcher.TM().GetAllTasksByMainTaskCodeFromDB(ctxTx, task.MainTaskCode)
			if err != nil {
				ctxTx.Rollback()
				return nil, err
			}
			for _, t2 := range tasks {
				if task.Id == t2.Id {
					continue
				}
				err = hg.dispatcher.TM().UpdateFocuseTaskStatusToDB(ctxTx, t2.Id, model.TaskStatusFinish, model.CompleteTypeAbnomal)
				if err != nil {
					ctxTx.Rollback()
					return nil, err
				}
			}
		}
	}

	if !isFirstTask {
		err := hg.dispatcher.TM().UpdateFocuseTaskStatusToDB(ctxTx, task.Id, newTaskState, p.CompleteType)
		if err != nil {
			ctxTx.Rollback()
			return nil, err
		}
	}
	// }
	//解除电梯的锁定
	if p.OperateCMD == model.TaskOperateCancel || p.OperateCMD == model.TaskOperateForceFinish {
		if task.Status != model.TaskStatusRegister && task.Status != model.TaskStatusAssign && task.Status != model.TaskStatusCharging {
			runSubtask, err := hg.dispatcher.TM().GetRunningSubtaskFromDB(ctxTx, task.AgvId)
			if err != nil {
				nextSubtask, err := hg.dispatcher.TM().GetWaitingSubtaskFromDB(ctxTx, task.AgvId)
				if nextSubtask == nil {
					ctxTx.Rollback()
					return nil, err
				}
				agv1 := hg.dispatcher.TRM().GetMapRelationAGVFromDB(ctx, nextSubtask.MapName, nextSubtask.TargetSiteID)
				agv2 := hg.dispatcher.TRM().GetMapRelationAGVFromDB(ctx, nextSubtask.MapName, nextSubtask.SwitchToSite)
				if nextSubtask.NextSwitchType == model.FloorRelation {
					hg.dispatcher.DM().ModifyElevatorOccupyToDB(ctxTx, nextSubtask.NextSwitchDeviceCopy, "")
				} else if nextSubtask.SwitchType == model.FloorRelation {
					hg.dispatcher.DM().ModifyElevatorOccupyToDB(ctxTx, nextSubtask.SwitchDeviceCopy, "")
				} else if nextSubtask.NextSwitchType == model.FactoryRealtion && agv1 == nextSubtask.AgvId {
					hg.dispatcher.DM().ModifyAreaSwitchOccupyToDB(ctxTx, nextSubtask.MapName, nextSubtask.TargetSiteID, "")
				} else if nextSubtask.SwitchType == model.FactoryRealtion && agv2 == nextSubtask.AgvId {
					hg.dispatcher.DM().ModifyAreaSwitchOccupyToDB(ctxTx, nextSubtask.MapName, nextSubtask.SwitchToSite, "")
				}
			} else {
				agv1 := hg.dispatcher.TRM().GetMapRelationAGVFromDB(ctx, runSubtask.MapName, runSubtask.TargetSiteID)
				agv2 := hg.dispatcher.TRM().GetMapRelationAGVFromDB(ctx, runSubtask.MapName, runSubtask.SwitchToSite)
				if runSubtask.NextSwitchType == model.FloorRelation {
					hg.dispatcher.DM().ModifyElevatorOccupyToDB(ctxTx, runSubtask.NextSwitchDeviceCopy, "")
				} else if runSubtask.SwitchType == model.FloorRelation {
					hg.dispatcher.DM().ModifyElevatorOccupyToDB(ctxTx, runSubtask.SwitchDeviceCopy, "")
				} else if runSubtask.NextSwitchType == model.FactoryRealtion && agv1 == runSubtask.AgvId {
					hg.dispatcher.DM().ModifyAreaSwitchOccupyToDB(ctxTx, runSubtask.MapName, runSubtask.TargetSiteID, "")
				} else if runSubtask.SwitchType == model.FactoryRealtion && agv2 == runSubtask.AgvId {
					hg.dispatcher.DM().ModifyAreaSwitchOccupyToDB(ctxTx, runSubtask.MapName, runSubtask.SwitchToSite, "")
				}
			}
		}
	}

	//更新子任务状态
	if isUpdateSubtaskStatus {
		//获取子任务
		runSubtask, err := hg.dispatcher.TM().GetRunningSubtaskFromDB(ctxTx, task.AgvId)
		if err != nil {
			ctxTx.Rollback()
			return nil, err
		}

		err = hg.dispatcher.TM().UpdateFocuseSubtaskStatusToDB(ctxTx, runSubtask.Id, newTaskState, false, p.CompleteType)
		if err != nil {
			ctxTx.Rollback()
			return nil, err
		}
	}

	//状态为已取消或已完成时，清除路径规划和删除所有子任务和任务绑定(任务状态是在执行的任务和已解析的任务)
	if (newTaskState == model.TaskStatusCanceled || newTaskState == model.TaskStatusFinish) && (task.Status.IsRunning() || task.Status == model.TaskStasusResolved || task.Status == model.TaskStatusError) {
		//清除全局路径(只清除路径，不清除锁)
		if errDeletePath := hg.dispatcher.TRM().DeleteRobotGlobalPaths(ctxTx, task.AgvId, task.MapName); errDeletePath != nil {
			ctxTx.Rollback()
			return nil, errDeletePath
		}

		//解除任务绑定
		if task.MainTaskCode == "" {
			log.Warnf("robot:%s DeleteMainTaskByAgvIdToDB", task.AgvId)
			err := hg.dispatcher.TM().DeleteMainTaskByAgvIdToDB(ctxTx, task.AgvId)
			if err != nil {
				ctxTx.Rollback()
				return nil, err
			}

		} else {
			err := hg.dispatcher.TM().UpdateMainTaskIdToDB(ctxTx, task.MainTaskCode, 0, task.AgvId)
			if err != nil {
				ctxTx.Rollback()
				log.Errorf("任务完成失败,数据库解除任务绑定失败  taskid:%d", task.Id)
				return nil, err
			}
		}
		//删除对应子任务
		err := hg.dispatcher.TM().DeleteSubtasksToDB(ctxTx, task.Id)
		if err != nil {
			ctxTx.Rollback()
			log.Errorf("任务完成失败，数据库删除子任务失败  taskid:%d", task.Id)
			return nil, err
		}

	}

	//解除锁定点
	switch {
	case freeCharger && task.Type == model.TaskTypeCharge:
		hg.dispatcher.GetmanualChargeLock().Lock()
		log.Warnf("强制完成任务，结束充电，任务号:%d agvId:%s", task.Id, task.AgvId)
		errFree := hg.dispatcher.CM().FinishCharger(ctx, task.Id, task.AgvId)
		hg.dispatcher.GetmanualChargeLock().Unlock()
		if errFree != nil {
			ctxTx.Rollback()
			return nil, errFree
		}
	case freeStandbyPoint && task.Type == model.TaskTypeStandBy:
		if errFree := hg.dispatcher.TRM().FreeRobotStandByPoint(ctx, task.AgvId); errFree != nil {
			ctxTx.Rollback()
			return nil, errFree
		}
	}

	ctxTx.Commit()
	//success
	if robotOperateCode == proto.TaskOperatePb_TaskFinish || robotOperateCode == proto.TaskOperatePb_TaskCancel {
		if task.AgvId != "" {
			robot := robotmanager.GetFromCache(task.AgvId)
			if robot.StatusIsExists() {
				robot.Status.IsBlock = false
			}
			robot.CanBeCancel = false
		}
	}
	return nil, nil
}

// @Summary 任务优先级更改
// @Description
// @Accept application/json
// @Produce application/json
// @Param body body changeTaskGradeParams true " "
// @Success 0 {object} ResponseExample "返回数据格式"
// @Tags 任务
// @Router /task/change_task_grade [post]
func (hg *HttpGateway) ChangeTaskGrade(ctx context.Context, params interface{}) (interface{}, codes.Code) {
	p := params.(*changeTaskGradeParams)
	return nil, hg.dispatcher.TM().TaskGradeChange(ctx, p.TaskIds, p.Grade)
}
